﻿#include "qtopencv.h"

QtOpencv::QtOpencv()
{

}

void QtOpencv::GetStringSize(HDC hDC, const char* str, int* w, int* h)
{
    SIZE size;
    GetTextExtentPoint32A(hDC, str, strlen(str), &size);
    if (w != 0) *w = size.cx;
    if (h != 0) *h = size.cy;
}

void QtOpencv::putTextZH(cv::Mat &dst, const char* str, cv::Point org, cv::Scalar color, int fontSize, const char* fn, bool italic, bool underline)
{
    CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3||dst.channels() == 4));
    if(dst.channels() == 1)
    {
        cv::cvtColor(dst,dst,cv::COLOR_GRAY2BGR);
    }
    else if(dst.channels() == 1)
    {
        cv::cvtColor(dst,dst,cv::COLOR_BGRA2RGB);

    }
    int x, y, r, b;
    if (org.x > dst.cols || org.y > dst.rows) return;
    x = org.x < 0 ? -org.x : 0;
    y = org.y < 0 ? -org.y : 0;

    LOGFONTA lf;
    lf.lfHeight = -fontSize;
    lf.lfWidth = 0;
    lf.lfEscapement = 0;
    lf.lfOrientation = 0;
    lf.lfWeight = 5;
    lf.lfItalic = italic;   //斜体
    lf.lfUnderline = underline; //下划线
    lf.lfStrikeOut = 0;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfOutPrecision = 0;
    lf.lfClipPrecision = 0;
    lf.lfQuality = PROOF_QUALITY;
    lf.lfPitchAndFamily = 0;
    strcpy_s(lf.lfFaceName, fn);

    HFONT hf = CreateFontIndirectA(&lf);
    HDC hDC = CreateCompatibleDC(0);
    HFONT hOldFont = (HFONT)SelectObject(hDC, hf);

    int strBaseW = 0, strBaseH = 0;
    int singleRow = 0;
    char buf[1 << 12];
    strcpy_s(buf, str);
    char *bufT[1 << 12];  // 这个用于分隔字符串后剩余的字符，可能会超出。
    //处理多行
    {
        int nnh = 0;
        int cw, ch;

        const char* ln = strtok_s(buf, "\n",bufT);
        while (ln != 0)
        {
            GetStringSize(hDC, ln, &cw, &ch);
            strBaseW = max(strBaseW, cw);
            strBaseH = max(strBaseH, ch);

            ln = strtok_s(0, "\n",bufT);
            nnh++;
        }
        singleRow = strBaseH;
        strBaseH *= nnh;
    }

    if (org.x + strBaseW < 0 || org.y + strBaseH < 0)
    {
        SelectObject(hDC, hOldFont);
        DeleteObject(hf);
        DeleteObject(hDC);
        return;
    }

    r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1;
    b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1;
    org.x = org.x < 0 ? 0 : org.x;
    org.y = org.y < 0 ? 0 : org.y;

    BITMAPINFO bmp = { 0 };
    BITMAPINFOHEADER& bih = bmp.bmiHeader;
    int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4));

    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = strBaseW;
    bih.biHeight = strBaseH;
    bih.biPlanes = 1;
    bih.biBitCount = 24;
    bih.biCompression = BI_RGB;
    bih.biSizeImage = strBaseH * strDrawLineStep;
    bih.biClrUsed = 0;
    bih.biClrImportant = 0;

    void* pDibData = 0;
    HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0);

    CV_Assert(pDibData != 0);
    HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp);

    //color.val[2], color.val[1], color.val[0]
    SetTextColor(hDC, RGB(255, 255, 255));
    SetBkColor(hDC, 0);
    //SetStretchBltMode(hDC, COLORONCOLOR);

    strcpy_s(buf, str);
    const char* ln = strtok_s(buf, "\n",bufT);
    int outTextY = 0;
    while (ln != 0)
    {
        TextOutA(hDC, 0, outTextY, ln, strlen(ln));
        outTextY += singleRow;
        ln = strtok_s(0, "\n",bufT);
    }
    uchar* dstData = (uchar*)dst.data;
    int dstStep = dst.step / sizeof(dstData[0]);
    unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep;
    unsigned char* pStr = (unsigned char*)pDibData + x * 3;
    for (int tty = y; tty <= b; ++tty)
    {
        unsigned char* subImg = pImg + (tty - y) * dstStep;
        unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep;
        for (int ttx = x; ttx <= r; ++ttx)
        {
            for (int n = 0; n < dst.channels(); ++n){
                double vtxt = subStr[n] / 255.0;
                int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n];
                subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv);
            }

            subStr += 3;
            subImg += dst.channels();
        }
    }

    SelectObject(hDC, hOldBmp);
    SelectObject(hDC, hOldFont);
    DeleteObject(hf);
    DeleteObject(hBmp);
    DeleteDC(hDC);
}

//"row|col|W|H"
void QtOpencv::drawRectangle1(cv::Mat srcdst, QString rectstr,const cv::Scalar& color,int thick)
{
    QStringList strlist=rectstr.split('|');
    cv::Rect rect=cv::Rect(strlist[0].toInt(),strlist[1].toInt(),strlist[2].toInt(),strlist[3].toInt());
    cv::rectangle(srcdst,rect,color, thick);
}
void QtOpencv::calculateRectInMat(cv::Mat image,QPoint firstPoint,QPoint lastPoint,QSize controlsize, QString *rectstr)
{
    //得宽高
    int w = image.cols;
    int h = image.rows;
    float row_ratio,col_ratio;
    row_ratio=float(w)/controlsize.width();
    col_ratio=float(h)/controlsize.height();
    int row,col,width,height;
    row=int(firstPoint.x()*row_ratio);
    col=int(firstPoint.y()*col_ratio);
    width=int((lastPoint.x()-firstPoint.x())*row_ratio);
    height=int((lastPoint.y()-firstPoint.y())*col_ratio);
    *rectstr=QString("%1|%2|%3|%4").arg(QString::number(row),QString::number(col),QString::number(width),QString::number(height));
}

void QtOpencv::calculateRect2InMat(cv::Mat src,cv::RotatedRect rotaterect,QSize controlsize, QString *rectstr)
{
    //得宽高
    if(src.empty())return;
    double ratio_x=double(src.cols)/controlsize.width();
    double ratio_y=double(src.rows)/controlsize.height();
    cv::RotatedRect rect=cv::RotatedRect(cv::Point2f(rotaterect.center.x*ratio_x,rotaterect.center.y*ratio_y),
                                         cv::Size(rotaterect.size.width*ratio_x,rotaterect.size.height*ratio_y),
                                         rotaterect.angle);
    *rectstr=QString("%1|%2|%3|%4|%5").arg(QString::number(rect.center.x,'f',3),QString::number(rect.center.y,'f',3),
                                           QString::number(rect.size.width,'f',3),QString::number(rect.size.height,'f',3),
                                           QString::number(rotaterect.angle,'f',3));
}


void QtOpencv::getMousePosGray(cv::Mat image,QPoint point,QSize controlsize,QPoint *pos,QVector<int> *value )
{
    QVector<int> grayValue=QVector<int>();
    //得宽高
    int w = image.cols;
    int h = image.rows;
    float row_ratio,col_ratio;
    row_ratio=float(w)/controlsize.width();
    col_ratio=float(h)/controlsize.height();
    int row,col;
    row=int(point.y()*col_ratio);
    col=int(point.x()*row_ratio);
    *pos=QPoint(row,col);
    int channels = image.channels();
    if (channels == 1)
    {
        //得到初始位置的迭代器
        cv::Mat_<uchar>::iterator it = image.begin<uchar>();
        //得到终止位置的迭代器
        cv::Mat_<uchar>::iterator itend = image.end<uchar>();
        int pixel = *(it + row * w + col);
        *value<<pixel;
    }
    else if (channels == 3)
    {
        //得到初始位置的迭代器
        cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>();
        //得到终止位置的迭代器
        cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>();
        //读取
        it = it + row * w + col;
        int b = (*it)[0];
        int g = (*it)[1];
        int r = (*it)[2];
        *value<<b<<g<<r;
    }
    else if (channels == 4)
    {
        //得到初始位置的迭代器
        cv::Mat_<cv::Vec4b>::iterator it = image.begin<cv::Vec4b>();
        //得到终止位置的迭代器
        cv::Mat_<cv::Vec4b>::iterator itend = image.end<cv::Vec4b>();
        //读取
        it = it + row * w + col;
        int b = (*it)[0];
        int g = (*it)[1];
        int r = (*it)[2];
        int a = (*it)[3];
        *value<<b<<g<<r<<a;
    }
}
//分离RGB图像
bool QtOpencv::departRGBImage(cv::Mat src,cv::Mat *r_image,cv::Mat *g_image,cv::Mat *b_image)
{
    if(src.empty())return false;
    cv::Mat img =src.clone();
    if(img.channels()!=3)return false;
    cv::Mat srcImage_B, srcImage_G, srcImage_R; //R、G、B各个通道
    std::vector<cv::Mat> channels_BGR;
    split(src, channels_BGR);
    //0通道为B分量，1通道为G分量，2通道为R分量。因为：RGB色彩空间在opencv中默认通道顺序为BGR！！！
    srcImage_B = channels_BGR.at(0);
    srcImage_G = channels_BGR.at(1);
    srcImage_R = channels_BGR.at(2);
    *b_image=srcImage_B.clone();
    *g_image=srcImage_G.clone();
    *r_image=srcImage_R.clone();
    return true;
}
//图像上绘制旋转矩形
bool QtOpencv::drawRotateRect(cv::Mat src,cv::RotatedRect rotaterect,QSize controlsize,cv::Scalar color, cv::Mat *dst)
{
    if(src.empty())return false;
    double ratio_x=double(src.cols)/controlsize.width();
    double ratio_y=double(src.rows)/controlsize.height();
    cv::RotatedRect rect=cv::RotatedRect( cv::Point2f(rotaterect.center.x*ratio_x,rotaterect.center.y*ratio_y),
                                          cv::Size(rotaterect.size.width*ratio_x,rotaterect.size.height*ratio_y),
                                          rotaterect.angle);
    cv::Mat dstImg=src.clone();
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);

    cv::Point2f rectPoints[4];
    rect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(dstImg,contour,0,color,5);
    *dst=dstImg.clone();
    return true;
}
//图像上绘制旋转矩形
bool QtOpencv::drawRotateRect(cv::Mat src,cv::RotatedRect rotaterect,cv::Scalar color,cv::Mat *dst)
{
    if(src.empty())return false;
    cv::Mat dstImg=src.clone();
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);

    cv::Point2f rectPoints[4];
    rotaterect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(dstImg,contour,0,color,5);
    *dst=dstImg.clone();
    return true;
}
//图像上绘制旋转矩形
bool QtOpencv::drawRotateRect(cv::Mat src,QString strrotaterect,cv::Scalar color,cv::Mat *dst)
{
    if(src.empty())return false;
    QStringList strlist=strrotaterect.split('|');
    if(strlist.size()<5)
    {
        *dst=src.clone();
        return false;
    }
    cv::Point2f center_=cv::Point2f(strlist[0].toFloat(),strlist[1].toFloat());
    cv::Size size_=cv::Size(strlist[2].toFloat(),strlist[3].toFloat());
    double angle= strlist[4].toDouble();
    cv::RotatedRect rect=cv::RotatedRect(center_,size_,angle);
    cv::Mat dstImg=src.clone();
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);
    cv::Point2f rectPoints[4];
    rect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(dstImg,contour,0,color,5);
    *dst=dstImg.clone();
    return true;
}
//获取旋转矩形区域，原始图像，旋转矩形，控件尺寸，是否摆正（摆正默认裁剪），是否裁剪，输出图像
bool QtOpencv::getRotateRectRoi(cv::Mat src,cv::RotatedRect rotaterect,QSize controlsize,bool isStraighten,bool iscut,cv::Mat *dst)
{
    if(src.empty())return false;
    double ratio_x=double(src.cols)/controlsize.width();
    double ratio_y=double(src.rows)/controlsize.height();
    cv::RotatedRect rect=cv::RotatedRect( cv::Point2f(rotaterect.center.x*ratio_x,rotaterect.center.y*ratio_y),
                                          cv::Size(rotaterect.size.width*ratio_x,rotaterect.size.height*ratio_y),
                                          rotaterect.angle);

    cv::Mat dstImg;
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);

    cv::Point2f rectPoints[4];
    rect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(mask,contour,0,cv::Scalar::all(255),-1);
    src.copyTo(dstImg,mask);
    if(isStraighten)
    {
        cv::Point2f center = rect.center;//外接矩形中心点坐标
        cv::Mat rot_mat = getRotationMatrix2D(center, rect.angle, 1.0);//求旋转矩阵
        cv::Size dst_sz(src.size());
        cv::warpAffine(src, dstImg, rot_mat, dst_sz);//原图像旋转
        *dst = dstImg(cv::Rect(center.x - (rect.size.width / 2), center.y - (rect.size.height/2), rect.size.width, rect.size.height));//提取ROI
        return  true;
    }
    if(iscut)
    {
        cv::Point2f point_upleft,point_bottomright;
        point_upleft = rect.center;
        for (int j = 0; j < 4; j++)
        {
            point_upleft.x = rectPoints[j].x < point_upleft.x ? rectPoints[j].x : point_upleft.x;    //矩形的右边长
            if(point_upleft.x<0)point_upleft.x=0;
            point_bottomright.x = rectPoints[j].x > point_bottomright.x ? rectPoints[j].x : point_bottomright.x;     //矩形的左边长
            if(point_bottomright.x>dstImg.cols)point_bottomright.x=dstImg.cols;
            point_upleft.y = rectPoints[j].y < point_upleft.y ? rectPoints[j].y : point_upleft.y;    //矩形的上边长
            if(point_upleft.y<0)point_upleft.y=0;
            point_bottomright.y = rectPoints[j].y > point_bottomright.y ? rectPoints[j].y : point_bottomright.y;     //矩形的下边长
            if(point_bottomright.y>dstImg.rows)point_bottomright.y=dstImg.rows;
        }
        cv::Rect rect1=cv::Rect(point_upleft,point_bottomright);
        *dst=dstImg(rect1);
        return true;
    }
    return true;
}
//获取旋转矩形区域，原始图像，旋转矩形，是否摆正（摆正默认裁剪），是否裁剪，输出图像
bool QtOpencv::getRotateRectRoi(cv::Mat src,QString strrotaterect,bool isStraighten,bool iscut,cv::Mat *dst)
{
    if(src.empty())return false;
    QStringList strlist=strrotaterect.split('|');
    if(strlist.size()<5)
    {
        *dst=src.clone();
        return false;
    }
    cv::Point2f center_=cv::Point2f(strlist[0].toFloat(),strlist[1].toFloat());
    cv::Size size_=cv::Size(strlist[2].toFloat(),strlist[3].toFloat());
    double angle= strlist[4].toDouble();

    cv::RotatedRect rect=cv::RotatedRect(center_,size_,angle);

    cv::Mat dstImg;
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);

    cv::Point2f rectPoints[4];
    rect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(mask,contour,0,cv::Scalar::all(255),-1);
    src.copyTo(dstImg,mask);
    if(isStraighten)
    {
        cv::Point2f center = rect.center;//外接矩形中心点坐标
        cv::Mat rot_mat = getRotationMatrix2D(center, rect.angle, 1.0);//求旋转矩阵
        cv::Size dst_sz(src.size());
        cv::warpAffine(src, dstImg, rot_mat, dst_sz);//原图像旋转
        *dst = dstImg(cv::Rect(center.x - (rect.size.width / 2), center.y - (rect.size.height/2), rect.size.width, rect.size.height));//提取ROI
        return  true;
    }
    if(iscut)
    {
        cv::Point2f point_upleft,point_bottomright;
        point_upleft = rect.center;
        for (int j = 0; j < 4; j++)
        {
            point_upleft.x = rectPoints[j].x < point_upleft.x ? rectPoints[j].x : point_upleft.x;    //矩形的右边长
            if(point_upleft.x<0)point_upleft.x=0;
            point_bottomright.x = rectPoints[j].x > point_bottomright.x ? rectPoints[j].x : point_bottomright.x;     //矩形的左边长
            if(point_bottomright.x>dstImg.cols)point_bottomright.x=dstImg.cols;
            point_upleft.y = rectPoints[j].y < point_upleft.y ? rectPoints[j].y : point_upleft.y;    //矩形的上边长
            if(point_upleft.y<0)point_upleft.y=0;
            point_bottomright.y = rectPoints[j].y > point_bottomright.y ? rectPoints[j].y : point_bottomright.y;     //矩形的下边长
            if(point_bottomright.y>dstImg.rows)point_bottomright.y=dstImg.rows;
        }
        cv::Rect rect1=cv::Rect(point_upleft,point_bottomright);
        *dst=dstImg(rect1);
        return true;
    }
    return true;
}

//获取旋转矩形区域，原始图像，旋转矩形，是否摆正（摆正默认裁剪），是否裁剪，输出图像
bool QtOpencv::getRotateRectRoi(cv::Mat src,cv::RotatedRect rect,bool isStraighten,bool iscut,cv::Mat *dst)
{
    if(src.empty())return false;
    cv::Mat dstImg;
    cv::Mat mask = cv::Mat::zeros(src.size(),CV_8UC1);

    cv::Point2f rectPoints[4];
    rect.points(rectPoints);
    std::vector<std::vector<cv::Point>> contour;
    std::vector<cv::Point> pts;
    for (int i=0;i<sizeof (rectPoints)/sizeof (rectPoints[0]);i++)
    {
        pts.push_back(rectPoints[i]);
    }
    contour.push_back(pts);
    drawContours(mask,contour,0,cv::Scalar::all(255),-1);
    src.copyTo(dstImg,mask);
    if(isStraighten)
    {
        cv::Point2f center = rect.center;//外接矩形中心点坐标
        cv::Mat rot_mat = getRotationMatrix2D(center, rect.angle, 1.0);//求旋转矩阵
        cv::Size dst_sz(src.size());
        cv::warpAffine(src, dstImg, rot_mat, dst_sz);//原图像旋转
        *dst = dstImg(cv::Rect(center.x - (rect.size.width / 2), center.y - (rect.size.height/2), rect.size.width, rect.size.height));//提取ROI
        return  true;
    }
    if(iscut)
    {
        cv::Point2f point_upleft,point_bottomright;
        point_upleft = rect.center;
        for (int j = 0; j < 4; j++)
        {
            point_upleft.x = rectPoints[j].x < point_upleft.x ? rectPoints[j].x : point_upleft.x;    //矩形的右边长
            if(point_upleft.x<0)point_upleft.x=0;
            point_bottomright.x = rectPoints[j].x > point_bottomright.x ? rectPoints[j].x : point_bottomright.x;     //矩形的左边长
            if(point_bottomright.x>dstImg.cols)point_bottomright.x=dstImg.cols;
            point_upleft.y = rectPoints[j].y < point_upleft.y ? rectPoints[j].y : point_upleft.y;    //矩形的上边长
            if(point_upleft.y<0)point_upleft.y=0;
            point_bottomright.y = rectPoints[j].y > point_bottomright.y ? rectPoints[j].y : point_bottomright.y;     //矩形的下边长
            if(point_bottomright.y>dstImg.rows)point_bottomright.y=dstImg.rows;
        }
        cv::Rect rect1=cv::Rect(point_upleft,point_bottomright);
        *dst=dstImg(rect1);
        return true;
    }
    return true;
}
//水平拼接direction为0，垂直为1
cv::Mat QtOpencv::connectMat(QList<cv::Mat> matlist,int direction)
{
    if(matlist.size()<1)return cv::Mat();

    if(direction==0)
    {
        int width=0;
        int height=matlist[0].rows;
        cv::Mat  resultImg;
        int matstart=0;
        for (int i=0;i<matlist.size();i++)
        {
            cv::Mat dst;
            cv::resize(matlist[i],dst,cv::Size(matlist[i].cols,height));
            width+=dst.cols;
            cv::Mat ori=resultImg.clone();
            if(matlist[0].channels()==1)
            {
                resultImg= cv::Mat(height, width, CV_8UC1, cv::Scalar::all(0));
            }
            else if(matlist[0].channels()==3)
            {
                resultImg= cv::Mat(height, width, CV_8UC3, cv::Scalar::all(0));
            }
            cv::Mat ROI = resultImg(cv::Rect(0, 0, ori.cols, ori.rows));
            ori.copyTo(ROI);
            ROI = resultImg(cv::Rect(matstart, 0, dst.cols, dst.rows));
            dst.copyTo(ROI);
            matstart+=dst.cols;

        }
        return resultImg;
    }
    else if(direction==1)
    {
        int width=matlist[0].cols;
        int height=0;
        cv::Mat  resultImg;
        int matstart=0;
        for (int i=0;i<matlist.size();i++)
        {
            cv::Mat dst;
            cv::resize(matlist[i],dst,cv::Size(width,matlist[i].rows));
            height+=dst.rows;
            cv::Mat ori=resultImg.clone();
            if(matlist[0].channels()==1)
            {
                resultImg= cv::Mat(height, width, CV_8UC1, cv::Scalar::all(0));
            }
            else if(matlist[0].channels()==3)
            {
                resultImg= cv::Mat(height, width, CV_8UC3, cv::Scalar::all(0));
            }
            cv::Mat ROI = resultImg(cv::Rect(0, 0, ori.cols, ori.rows));
            ori.copyTo(ROI);
            ROI = resultImg(cv::Rect(0, matstart, dst.cols, dst.rows));
            dst.copyTo(ROI);
            matstart+=dst.rows;

        }
        return resultImg;
    }
}

/*cv::Mat labels, stats, centroids;
int roinum=cv::connectedComponentsWithStats(check_img, labels, stats,centroids);*/
cv::Mat QtOpencv::selectShape(cv::Mat src,cv::ConnectedComponentsTypes select_type,int min,int max)
{
    cv::Mat labels, stats, centroids;
    int roiNum=cv::connectedComponentsWithStats(src, labels, stats,centroids);
    std::vector<int> colors(roiNum);
    colors[0] =0; // background pixels remain black.
    switch (select_type)
    {
    case cv::CC_STAT_TOP:
        for( int i = 1; i < roiNum; i++ )
        {
            int a=stats.at<int>(i, cv::CC_STAT_TOP);
            if( stats.at<int>(i, cv::CC_STAT_TOP)>=min && stats.at<int>(i, cv::CC_STAT_TOP) <= max  )
                colors[i] = 255; // small regions are painted with black too.
            else
                colors[i] = 0;
        }
        break;
    case cv::CC_STAT_LEFT:
        for( int i = 1; i < roiNum; i++ )
        {
            int a=stats.at<int>(i, cv::CC_STAT_LEFT);
            if( stats.at<int>(i, cv::CC_STAT_LEFT)>=min && stats.at<int>(i, cv::CC_STAT_LEFT) <= max  )
                colors[i] = 255; // small regions are painted with black too.
            else
                colors[i] = 0;
        }
        break;
    case cv::CC_STAT_WIDTH:
        for( int i = 1; i < roiNum; i++ )
        {
            int a=stats.at<int>(i, cv::CC_STAT_WIDTH);
            if( stats.at<int>(i, cv::CC_STAT_WIDTH)>=min && stats.at<int>(i, cv::CC_STAT_WIDTH) <= max  )
                colors[i] = 255; // small regions are painted with black too.
            else
                colors[i] = 0;
        }
        break;
    case cv::CC_STAT_HEIGHT:
        for( int i = 1; i < roiNum; i++ )
        {
            int a=stats.at<int>(i, cv::CC_STAT_HEIGHT);
            if( stats.at<int>(i, cv::CC_STAT_HEIGHT)>=min && stats.at<int>(i, cv::CC_STAT_HEIGHT) <= max  )
                colors[i] = 255; // small regions are painted with black too.
            else
                colors[i] = 0;
        }
        break;
    case cv::CC_STAT_AREA:
        for( int i = 1; i < roiNum; i++ )
        {
            int a=stats.at<int>(i, cv::CC_STAT_AREA);
            if( stats.at<int>(i, cv::CC_STAT_AREA)>=min && stats.at<int>(i, cv::CC_STAT_AREA) <= max  )
                colors[i] = 255; // small regions are painted with black too.
            else
                colors[i] = 0;
        }
        break;
    }
    cv::Mat img = cv::Mat::zeros(src.size(), CV_8UC1);
    for( int y = 0; y < img.rows; y++ )
    {
        for( int x = 0; x < img.cols; x++ )
        {
            int label = labels.at<int>(y, x);
            CV_Assert(0 <= label && label <= roiNum);
            img.at<uchar>(y, x) = colors[label];
        }
    }
    return img;
}
void QtOpencv::rotateImage(cv::Mat &src,cv::Mat &dst,float angle)
{
    if(angle==90.0)
    {
        dst= cv::Mat(src.rows, src.cols,src.depth());
        cv::transpose(src, dst);
        cv::flip(dst, dst, 0);  //rotate 90
    }
    else if (angle==180)
    {
        flip(src, dst, -1);
    }
    else if (angle==270)
    {
        dst= cv::Mat(src.rows, src.cols,src.depth());
        cv::transpose(src, dst);
        cv::flip(dst, dst, 1);  //rotate 90
    }
    else
    {
        float radian = (float) (angle /180.0 * CV_PI);
        //填充图像
        int maxBorder =(int) (max(src.cols, src.rows)* 1.414 ); //即为sqrt(2)*max
        int dx = (maxBorder - src.cols)/2;
        int dy = (maxBorder - src.rows)/2;
        copyMakeBorder(src, dst, dy, dy, dx, dx, cv::BORDER_CONSTANT);

        //旋转
        cv::Point2f center( (float)(dst.cols/2) , (float) (dst.rows/2));
        cv::Mat affine_matrix =getRotationMatrix2D( center, angle, 1.0 );//求得旋转矩阵
        warpAffine(dst, dst, affine_matrix, dst.size());

        //计算图像旋转之后包含图像的最大的矩形
        float sinVal = abs(sin(radian));
        float cosVal = abs(cos(radian));
        cv::Size targetSize( (int)(src.cols * cosVal +src.rows * sinVal),
                             (int)(src.cols * sinVal + src.rows * cosVal) );

        //剪掉多余边框
        int x = (dst.cols - targetSize.width) / 2;
        int y = (dst.rows - targetSize.height) / 2;
        cv::Rect rect(x, y, targetSize.width, targetSize.height);
        dst = cv::Mat(dst,rect);
        return;
    }
}

void QtOpencv::erisionRectangle1(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(width, height));
    cv::erode(src, dst,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);

}
void QtOpencv::dilateRectangle1(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(width, height));
    cv::dilate(src, dst,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);

}
void QtOpencv::erisionCircle(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(width, height));
    cv::erode(src, dst,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
void QtOpencv::dilateCircle(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(width, height));
    cv::dilate(src, dst,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
void QtOpencv::openingRectangle1(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(width, height));
    cv::morphologyEx(src, dst,cv::MORPH_OPEN,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
void QtOpencv::closingRectangle1(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_RECT, cv::Size(width, height));
    cv::morphologyEx(src, dst,cv::MORPH_CLOSE,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
void QtOpencv::openingCircle(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(width, height));
    cv::morphologyEx(src, dst,cv::MORPH_OPEN,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
void QtOpencv::closingCircle(cv::Mat src,cv::Mat dst,int width,int height)
{
    cv::Mat element = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(width, height));
    cv::morphologyEx(src, dst,cv::MORPH_CLOSE,element);
    //cv::threshold(dst,dst,250,255,cv::THRESH_BINARY);
}
cv::Mat QtOpencv::paintImageToRect(cv::Mat src,cv::Mat paintImage,cv::Rect rect)
{
    cv::Mat dst=src.clone();
    cv::Mat image;
    cv::resize(paintImage,image,rect.size());
    cv::Mat ROI = dst(rect);
    image.copyTo(ROI);
    return dst;
}
cv::Mat QtOpencv::scaleImage(cv::Mat src,cv::Size size,int channels)
{
    cv::Mat op_mat=src.clone();
    //新建空白图像
    cv::Mat image_scale(size,CV_8UC(channels), cv::Scalar(0,0,0));
    //计算缩放比例
    float scale_x=float(op_mat.cols)/size.width;
    float scale_y=float(op_mat.rows)/size.height;
    float scale_ratio=(scale_x>scale_y?scale_x:scale_y);
    //计算缩放后的尺寸
    int new_rows,new_cols;
    scale_x>=scale_y?scale_y=scale_x:scale_x=scale_y;
    new_cols=int(op_mat.cols/scale_ratio);
    new_cols>size.width?new_cols=size.width:new_cols;
    new_rows=int(op_mat.rows/scale_ratio);
    new_rows>size.height?new_rows=size.height:new_rows;
    //计算偏移尺寸
    int move_x,move_y;
    move_x=(size.width-new_cols)/2;
    move_y=(size.height-new_rows)/2;
    //等比例缩放并边缘为0
    cv::resize(op_mat,op_mat,cv::Size(new_cols,new_rows));
    op_mat.copyTo(image_scale(cv::Rect(move_x,move_y,new_cols,new_rows)));
    return image_scale;
}






